﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bronze.XXT.PhoneServer
{
    public class Message
    {
        public int command_length
        {
            get;
            set;
        }


        private string funcno;
        public string func_no
        {
            get
            {
                if (string.IsNullOrEmpty(funcno) && Body != null)
                {
                    var msgBodyAttr = MsgAttribute.GetData(this.Body.GetType());
                    if (msgBodyAttr != null)
                    {
                        funcno = msgBodyAttr.func_no;
                    }
                }
                return funcno;
            }
            set
            {
                funcno = value;
            }
        }

        public string seq_no;

        public MessageBody Body
        {
            get;
            set;
        }
        /// <summary>
        /// 是否话机向服务器
        /// </summary>
        public bool IsRequest
        {
            get;
            set;
        }

        public byte[] GetBytes()
        {
            //byte[] bytes = new byte[command_length];
            var array_func_no = Encoding.Default.GetBytes(func_no);

            var array_seq_no = Encoding.Default.GetBytes(seq_no);
            var array_body = Body.GetBytes();
            command_length = 10 + array_body.Length;
            var array_len = Encoding.Default.GetBytes(command_length.ToString().PadLeft(4, '0'));
            return array_len
                .Concat(array_func_no)
                .Concat(array_seq_no)
                .Concat(array_body)
                .ToArray();

        }

        public static List<Message> FromBytes(byte[] bytes, bool isRequest)
        {
            List<Message> messages = new List<Message>();

            Action<int> parserMessage = null;
            parserMessage = (start) =>
            {
                byte[] package;
                if (start == 0)
                {
                    package = bytes;
                }
                else
                {
                    package = new byte[bytes.Length - start];
                    Array.Copy(bytes, start, package, 0, bytes.Length - start);
                }

                var length = Encoding.Default.GetString(package, 0, 4);
                var func = Encoding.Default.GetString(package, 4, 2);
                var seq_no = Encoding.Default.GetString(package, 6, 4);
                Message msg = new Message();
                msg.command_length = Convert.ToInt32(length);
                msg.func_no = func;
                msg.seq_no = seq_no;
                Type bodyType = ProgramCache.MESSAGEBODY_TYPES_CACHE[msg.func_no + (Convert.ToInt32(isRequest)).ToString()];//区分收到和发送
                if (bodyType != null)
                {
                    msg.Body = Activator.CreateInstance(bodyType) as MessageBody;
                    msg.Body.FromBytes(package);
                }
                messages.Add(msg);
                int msgLength = Convert.ToInt32(length);
                if (package.Length > msgLength && package[msgLength] != '\0')
                {
                    parserMessage(start + msgLength);
                }
            };

            try
            {
                parserMessage(0);
            }
            catch (Exception ex)
            {
                //TODO 处理异常，或者屏蔽
                return new List<Message>();
            }

            return messages;
        }


        public static byte[] MessagesToBytes(params Message[] messages)
        {
            byte[] bytes = new byte[] { };
            foreach (var msg in messages)
            {
                if (bytes == null)
                {
                    bytes = msg.GetBytes();
                }
                else
                {
                	bytes=bytes.Concat(msg.GetBytes()).ToArray();
                }
            }
            return bytes;
        }

    }
}
